﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Utilities;

namespace NetTopologySuite.Noding
{
	public class ScaledNoder : INoder
	{
		public ScaledNoder(INoder noder, double scaleFactor) : this(noder, scaleFactor, 0.0, 0.0)
		{
		}

		[Obsolete("Do not use offsetX and offsetY")]
		public ScaledNoder(INoder noder, double scaleFactor, double offsetX, double offsetY)
		{
			this._noder = noder;
			this._scaleFactor = scaleFactor;
			this._offsetX = offsetX;
			this._offsetY = offsetY;
			this._isScaled = !this.IsIntegerPrecision;
		}

		public bool IsIntegerPrecision
		{
			get
			{
				return this._scaleFactor == 1.0;
			}
		}

		public IList<ISegmentString> GetNodedSubstrings()
		{
			IList<ISegmentString> nodedSubstrings = this._noder.GetNodedSubstrings();
			if (this._isScaled)
			{
				this.Rescale(nodedSubstrings);
			}
			return nodedSubstrings;
		}

		public void ComputeNodes(IList<ISegmentString> inputSegStrings)
		{
			IList<ISegmentString> segStrings = inputSegStrings;
			if (this._isScaled)
			{
				segStrings = this.Scale(inputSegStrings);
			}
			this._noder.ComputeNodes(segStrings);
		}

		private IList<ISegmentString> Scale(IList<ISegmentString> segStrings)
		{
			return CollectionUtil.Transform<ISegmentString, ISegmentString>(segStrings, (ISegmentString ss) => new NodedSegmentString(this.Scale(ss.Coordinates), ss.Context));
		}

		private Coordinate[] Scale(Coordinate[] pts)
		{
			Coordinate[] array = new Coordinate[pts.Length];
			for (int i = 0; i < pts.Length; i++)
			{
				array[i] = new Coordinate(System.Math.Round((pts[i].X - this._offsetX) * this._scaleFactor), System.Math.Round((pts[i].Y - this._offsetY) * this._scaleFactor), pts[i].Z);
			}
			return CoordinateArrays.RemoveRepeatedPoints(array);
		}

		private void Rescale(IList<ISegmentString> segStrings)
		{
			CollectionUtil.Apply<ISegmentString>(segStrings, delegate(ISegmentString ss)
			{
				this.Rescale(ss.Coordinates);
				return null;
			});
		}

		private void Rescale(Coordinate[] pts)
		{
			if (pts.Length == 2)
			{
				new Coordinate(pts[0]);
				new Coordinate(pts[1]);
			}
			for (int i = 0; i < pts.Length; i++)
			{
				pts[i].X = pts[i].X / this._scaleFactor + this._offsetX;
				pts[i].Y = pts[i].Y / this._scaleFactor + this._offsetY;
			}
			if (pts.Length == 2)
			{
				pts[0].Equals2D(pts[1]);
			}
		}

		private readonly INoder _noder;

		private readonly double _scaleFactor;

		private readonly double _offsetX;

		private readonly double _offsetY;

		private readonly bool _isScaled;
	}
}
